package com.sxx.mall.ware.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sxx.commons.dto.SkuHasStockDTO;
import com.sxx.commons.exception.NoStockException;
import com.sxx.commons.utils.PageUtils;
import com.sxx.commons.utils.Query;
import com.sxx.commons.utils.R;
import com.sxx.mall.ware.dao.WareSkuDao;
import com.sxx.mall.ware.entity.WareSkuEntity;
import com.sxx.mall.ware.feign.ProductFeignService;
import com.sxx.mall.ware.service.WareSkuService;
import com.sxx.mall.ware.vo.LockStockResult;
import com.sxx.mall.ware.vo.OrderItemVO;
import com.sxx.mall.ware.vo.WareSkuLockVO;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service("wareSkuService")
public class WareSkuServiceImpl extends ServiceImpl<WareSkuDao, WareSkuEntity> implements WareSkuService {

    @Autowired
    private WareSkuDao wareSkuDao;
    @Autowired
    private ProductFeignService productFeignService;

    @Autowired
    private WareSkuService wareSkuService;

    //skuId=&wareId=2
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        QueryWrapper<WareSkuEntity> wrapper = new QueryWrapper<>();
        String skuId = (String) params.get("skuId");
        if (!StringUtils.isEmpty(skuId)){
            wrapper.eq("sku_id",skuId);
        }
        String wareId = (String) params.get("wareId");
        if (!StringUtils.isEmpty(wareId)){
            wrapper.eq("ware_id",wareId);
        }
        IPage<WareSkuEntity> page = this.page(
                new Query<WareSkuEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    /**
     * 入库财政
     * @param skuId 商品编号
     * @param wareId 仓库编号
     * @param skuNum 采购商品的数量
     */
    @Override
    public void addStock(Long skuId, Long wareId, Integer skuNum) {
        //判断是否有该商品和仓库的入库记录
        List<WareSkuEntity> wareSkuEntities = wareSkuDao
                .selectList(new QueryWrapper<WareSkuEntity>()
                        .eq("sku_id", skuId)
                        .eq("ware_id", wareId));
        if (wareSkuEntities == null || wareSkuEntities.size() == 0){
            //如果没有就新增商品库存记录
            WareSkuEntity wareSkuEntity = new WareSkuEntity();
            wareSkuEntity.setSkuId(skuId);
            wareSkuEntity.setWareId(wareId);
            wareSkuEntity.setStock(skuNum);
            wareSkuEntity.setStockLocked(0);
            try{
                //动态设置商品名称
                R info = productFeignService.info(skuId);
                Map<String,Object> data = (Map<String, Object>) info.get("skuInfo");
                if (info.getCode() == 0){
                    wareSkuEntity.setSkuName((String) data.get("skuName"));
                }
            }catch (Exception e){

            }

            wareSkuDao.insert(wareSkuEntity);
        }else {
            //如果有就更新库存
            wareSkuDao.addStock(skuId,skuNum,wareId);
        }
    }

    /*
    * 是否有库存
    * */
    @Override
    public List<SkuHasStockDTO> hasStock(List<Long> skuIds) {
        List<SkuHasStockDTO> skuHasStockDTOS = skuIds.stream().map(skuId -> {
            QueryWrapper<WareSkuEntity> wrapper = new QueryWrapper<WareSkuEntity>().eq("sku_id", skuId);
            List<WareSkuEntity> list = wareSkuService.list(wrapper);
            SkuHasStockDTO skuHasStockDTO = new SkuHasStockDTO();
            list.forEach(wareSkuEntity -> {
                if (wareSkuEntity.getStock() - wareSkuEntity.getStockLocked() > 0) {
                    skuHasStockDTO.setHasStock(true);
                    skuHasStockDTO.setSkuId(wareSkuEntity.getSkuId());
                }
            });
            return skuHasStockDTO;
        }).collect(Collectors.toList());
        return skuHasStockDTOS;
    }

    /**
     * 锁定库存操作
     * @param vo
     * @return
     */
    @Transactional
    @Override
    public Boolean orderLockStock(WareSkuLockVO vo) {
        List<OrderItemVO> items = vo.getItems();
        //首先找到具有库存的仓库
        List<SkuWareHasStock> collect = items.stream().map(item -> {
            SkuWareHasStock skuWareHasStock = new SkuWareHasStock();
            skuWareHasStock.setSkuId(item.getSkuId());
            List<WareSkuEntity> wareSkuEntities = this.baseMapper.listHasStock(item.getSkuId());
            skuWareHasStock.setWareSkuEntities(wareSkuEntities);
            skuWareHasStock.setNum(item.getCount());
            return skuWareHasStock;
        }).collect(Collectors.toList());
        //尝试锁定库存
        for (SkuWareHasStock skuWareHasStock : collect) {
            Long skuId = skuWareHasStock.getSkuId();
            List<WareSkuEntity> wareSkuEntities = skuWareHasStock.getWareSkuEntities();
            if (wareSkuEntities == null && wareSkuEntities.size() == 0){
                //当前商品没有库存了
                throw new NoStockException(skuId);
            }
            //当前需要锁定的商品的数量
            Integer count = skuWareHasStock.getNum();
            Boolean skuStocked = false;//表示当前skuId的库存没有锁定完成
            for (WareSkuEntity wareSkuEntity : wareSkuEntities) {
                //循环获取到对应的仓库，然后需要锁定库存
                //获取当前仓库能够锁定的库存数
                Integer canStock = wareSkuEntity.getStock() - wareSkuEntity.getStockLocked();
                if (count <= canStock){
                    //表示当前库存可以满足该订单需求
                    Integer i = this.baseMapper.lockSkuStock(skuId,wareSkuEntity.getWareId(),count);
                    count = 0;
                    skuStocked = true;
                }else {
                    Integer i = this.baseMapper.lockSkuStock(skuId,wareSkuEntity.getWareId(),canStock);
                    count = count - canStock;
                }
                if (count <= 0){
                    //表示商品锁定完成
                    break;
                }
            }
            if (count > 0){
                //库存没有锁定完，库存不足
                throw new NoStockException(skuId);
            }
            if (skuStocked == false){
                //表示上一个商品没有锁定库存成功
                throw new NoStockException(skuId);
            }
        }
        return true;
    }

    @Data
    class SkuWareHasStock{
        private Long skuId;
        private Integer num;
        private List<WareSkuEntity> wareSkuEntities;
    }

}